﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using TekaMUD.Engine.Framework;

namespace TekaMUD.Engine.Blocks
{
	/// <summary>
	/// Database of runtime options, global to the entire application.
	/// </summary>
	public class RuntimeOptions
	{
		private static Dictionary<RuntimeOption, Object> GlobalOptions;
		private static Object SyncRoot = new object();

		static RuntimeOptions()
		{
			GlobalOptions = new Dictionary<RuntimeOption, object>();
		}

		public static void SetOption(string option, string value)
		{
			lock (SyncRoot)
			{
				try
				{
					RuntimeOption ro = (RuntimeOption)Enum.Parse(typeof(RuntimeOption), option, true);
					FieldInfo fi = typeof(RuntimeOption).GetField(ro.ToString());

					RuntimeOptionTargetTypeAttribute rotta = ((RuntimeOptionTargetTypeAttribute[])fi.GetCustomAttributes(typeof(RuntimeOptionTargetTypeAttribute), false))[0];


					// Check to see if this can be made generically.
					if (rotta.TargetType == typeof(string))
						GlobalOptions[ro] = value;
					else if (rotta.TargetType == typeof(int))
						GlobalOptions[ro] = int.Parse(value);
					else if (rotta.TargetType.IsEnum)
						GlobalOptions[ro] = Enum.Parse(rotta.TargetType, value, true);
					else if (rotta.TargetType == typeof(bool))
						GlobalOptions[ro] = Boolean.Parse(value);
					else
						throw new Exception("Invalid value: " + value);
				}
				catch(Exception)
				{
					throw new Exception("Invalid option: " + option);
				}
			}
		}

		public static KeyValuePair<RuntimeOption, object>[] ListAllOptions()
		{
			lock (SyncRoot)
			{
				KeyValuePair<RuntimeOption, object>[] ret = GlobalOptions.ToArray();

				Array.Sort<KeyValuePair<RuntimeOption, object>>(
					ret, 
					delegate(KeyValuePair<RuntimeOption, object> A, KeyValuePair<RuntimeOption, object> B)
					{ 
						return A.Key.CompareTo(B.Key); 
					});

				return ret;
			}
		}

		public static object GetOption(RuntimeOption option)
		{
			lock (SyncRoot)
				if (GlobalOptions.ContainsKey(option))
					return GlobalOptions[option];
				else
					return null;
		}

		public static Dictionary<string, string> DumpOptions()
		{
			lock (SyncRoot)
			{
				Dictionary<string, string> ret = new Dictionary<string, string>();

				foreach (KeyValuePair<RuntimeOption, object> kvp in GlobalOptions)
					ret.Add(kvp.Key.ToString(), kvp.Value.ToString());

				return ret;
			}

		}
	}

	public enum RuntimeOption
	{
		[RuntimeOptionTargetType(typeof(DebugLevel))]
		DebugLevel,

		[RuntimeOptionTargetType(typeof(bool))]
		DebugActive,

		[RuntimeOptionTargetType(typeof(bool))]
		UseTrace
	}

	[AttributeUsage(AttributeTargets.Field)]
	public class RuntimeOptionTargetTypeAttribute : Attribute
	{
		public Type TargetType { get; private set; }
		
		public RuntimeOptionTargetTypeAttribute(Type targetType)
		{
			this.TargetType = targetType;
		}
	}
}